# -*- coding: utf-8 -*-
import json
import logging
from decimal import Decimal

from datetime import timedelta
from dateutil import parser
from common.pay import db as pay_db

from api.lottery import ORDER_LOGIC
from api.lottery.model import *
from api.lottery.model import WaitShowOrder
from common.lottery import db
from common.lottery.cyclical import ORDER_STATUS
from common.lottery.cyclical.abstract import activity as cyclical_activity
from common.lottery.cyclical.abstract import order as cyclical_order
from common.lottery.model import OrderIndex
from common.timer.cyclical_handler import ACTIVITY_OFFSET as CYCICAL_OFFSET
from common.utils import exceptions as err
from common.utils import tz
from common.utils.api import page2offset
from common.utils.decorator import sql_wrapper, slave_wrapper
from common.preset.db import pay as preset_db
from common.pay.model import PAY_STATUS


_LOGGER = logging.getLogger(__name__)


def get_summary(lottery_list):
    summary = db.get_summary(lottery_list)
    resp = {}
    for lottery_type, data in summary.iteritems():
        resp[lottery_type] = []
        for d in data:
            resp[lottery_type].append(SummaryModel(d))
    return resp


def get_history_v2(user_id, params, page, size, need_order=True):
    limit, offset = page2offset(page, size)
    try:
        params['start_date'] = parser.parse(params['start_date'])
    except Exception:
        raise err.ParamError('start_date format error')
    params['start_date'] = tz.local_to_utc(params['start_date'])
    func = db.get_order_history if need_order else db.get_track_history
    items = func(user_id, params, limit, offset)
    resp = []
    model = OrderRecord if need_order else TrackRecordV2
    for item in items:
        data = model(item)
        if model is TrackRecordV2:
            _logic = ORDER_LOGIC[data['activity_type']]
            data['group_count'] = _logic.calc_total_price(data['bet_type'], data['number']) / _logic.UNIT
        if 'win_price' in data and not data['win_price']:
            data['win_price'] = 0
        resp.append(data)

    return resp


@sql_wrapper
def get_cyclical_order_history_v2(user_id, activity_type, page, size,
                                  track_id=None):
    limit, offset = page2offset(page, size)
    items = cyclical_order.get_history(activity_type, user_id, limit, offset,
                                       track_id)
    resp_items = []
    for item in items:
        data = CyclicalOrderRecordV2(item.as_dict())
        data.activity_type = activity_type
        data.created_at = tz.utc_to_local_str(item.created_at)
        data.updated_at = tz.utc_to_local_str(item.updated_at)
        resp_items.append(data)
    return resp_items


@sql_wrapper
def get_cyclical_order_detail_v2(user_id, activity_type, order_id):
    order = cyclical_order.get_order(activity_type, user_id, order_id)
    # 增加投注注数字段:group_count
    order_dict = order.as_dict()
    order_dict['group_count'] = int(
        Decimal(order_dict['price']) / Decimal(order_dict['unit']) / Decimal(order_dict['times']))
    data = CyclicalOrderDetailV2(order_dict)
    data.activity_type = activity_type
    data.updated_at = tz.utc_to_local_str(order.updated_at)
    data.created_at = tz.utc_to_local_str(order.created_at)
    ac = cyclical_activity.get_activity_by_term(activity_type, data.term)
    if ac and ac.number:
        data.win_number = ac.number if ',' in ac.number else ','.join(
            ac.number)
        data.left_ts = 0
    else:
        data.win_number = None
        data.left_ts = ac.end_ts - tz.now_ts() + CYCICAL_OFFSET[activity_type]
    return data


@sql_wrapper
def get_cyclical_track_detail_v2(user_id, activity_type, track_id):
    track = db.get_track_detail(user_id, int(activity_type), int(track_id))
    data = TrackRecordV2(track)
    _logic = ORDER_LOGIC[activity_type]
    data['group_count'] = _logic.calc_total_price(data['bet_type'], data['number']) / _logic.UNIT
    return data


@sql_wrapper
def get_cyclical_latest_activity(activity_type, param=None):
    ac = cyclical_activity.get_latest_term(activity_type)
    if not ac:
        raise err.ServerError('activity has 0 term, activity_type: %s' % activity_type)
    resp = CyclicalActivity(ac.as_dict())
    if resp.number and ',' not in resp.number:
        resp.number = ','.join(resp.number)
    resp.type = activity_type

    if param:
        if db.check_stop_lottery(activity_type, param['chn'], param['cvc']):
            _LOGGER.error("activity currently stopped: %s", activity_type)
            if int(param['cvc']) >= 20:
                raise err.InvalidLottery()
            raise err.NoTerm()

    resp.left_ts = ac.end_ts - tz.now_ts()
    if resp.left_ts < 0:
        raise err.NoTerm("no ongoing term for activity %s, end_ts: %s, now_ts: %s" %
                         (activity_type, ac.end_ts, tz.now_ts()))
    return resp


@slave_wrapper
def get_cyclical_activity_history(activity_type, last_n, status, page, size, sort):
    limit, offset = page2offset(page, size)
    items = cyclical_activity.get_activity_history(activity_type, last_n, status, limit, offset, sort)
    resp_items = []
    for item in items:
        data = CyclicalActivity(item.as_dict())
        if item.announce_ts:
            data.announce_at = tz.utc_to_local_str(datetime.fromtimestamp(item.announce_ts))
        data.type = activity_type
        if data.number and ',' not in data.number:
            data.number = ','.join(data.number)
        resp_items.append(data)

    return resp_items


@sql_wrapper
def get_stats(activity_type, bet_type):
    bet_types = bet_type.split(',')
    resp = {}
    for bet_type in bet_types:
        resp[bet_type] = cyclical_activity.get_stats_by_bet_type(activity_type, int(bet_type))
    return resp


def get_read_stats(user_id):
    return db.get_user_read_stats(user_id)


@sql_wrapper
def view_wait_show_orders(user_id, page, size):
    limit, offset = page2offset(page, size, max_size=30, default_size=20)
    query = OrderIndex.query.filter(
        OrderIndex.user_id == user_id).filter(
        OrderIndex.status == ORDER_STATUS.WINNED).filter(
        OrderIndex.detail.isnot(None)).order_by(OrderIndex.id.desc())
    if limit:
        query = query.limit(limit)
    if offset:
        query = query.offset(offset)

    return query.all()


def create_wait_show_order_lite(orders):
    order_lites = []
    for order in orders:
        order_lite = WaitShowOrder()
        order_lite.activity_type = order.activity_type
        order_lite.order_id = order.order_id

        order_detail = json.loads(order.detail)
        order_lite.term = order_detail['term']
        order_lite.price = order_detail['price']
        order_lite.win_price = order_detail['win_price']

        order_lites.append(order_lite)

    return order_lites


def get_pay_record_list(user_id, page, size):
    limit, offset = page2offset(page, size, max_size=30, default_size=20)

    pay_list, total = pay_db.get_pay_record_by_user_id(user_id, limit, offset)
    for pay in pay_list:
        preset_pay = preset_db.get_pay_preset_by_type(pay['pay_type'])
        pay['pay_type_desc'] = preset_pay and preset_pay.title
        del pay['third_id']
        pay['extend'] = pay['extend'] and json.loads(pay['extend'])
        if pay['status'] != PAY_STATUS.DONE and pay['created_at'] + timedelta(days=3) < datetime.now():
            pay['status'] = PAY_STATUS.FAIL

        pay['created_at'] = tz.utc_to_local_str(pay['created_at'])

    return pay_list, total
